package com.njcb.ams.service.workflow;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.TaskQueryImpl;
import org.activiti.engine.impl.persistence.entity.SuspensionState;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.NativeTaskQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.njcb.ams.pojo.vo.ApprovalCommentsVO;
import com.njcb.ams.pojo.vo.RunTaskQueryVO;
import com.njcb.ams.factory.comm.DataBus;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.util.AmsAssert;
import com.njcb.ams.util.AmsUtils;
import com.njcb.ams.util.WorkFlowVariable;
import com.njcb.ams.util.WorkFlowVariable.ApprovalResult;
import com.njcb.ams.util.WrokflowServiceUtils;

/**
 * 流程任务处理服务
 * 
 * @author liuyanlong
 *
 */
@Service
public class WrokflowTaskService {
	@Autowired
	private ProcessDiagramService processDiagramService;
	@Autowired
	private RuntimeService rumtimeService;
	@Autowired
	private TaskService taskService;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private ManagementService managementService;

	/**
	 * 查询用户待办任务
	 * 
	 * @param userid
	 * @return
	 */
	public List<Task> queryTaskByUserId(String userid) {
		List<Task> tasks = taskService.createTaskQuery().taskAssignee(userid).list();
		return tasks;
	}

	/**
	 * 查询代办任务
	 * 
	 * @param queryBean
	 * @return
	 */
	public List<Task> queryRuTask(RunTaskQueryVO queryBean) {
		
		TaskQueryImpl query = (TaskQueryImpl) taskService.createTaskQuery();
		if(AmsUtils.isNotNull(queryBean.getNameLike())){
			query.taskNameLike(queryBean.getNameLike());
		}

		if(AmsUtils.isNotNull(queryBean.getSuspensionState())){
			if(SuspensionState.SUSPENDED.getStateCode() == queryBean.getSuspensionState()){
				query.suspended();
			}else if(SuspensionState.ACTIVE.getStateCode() == queryBean.getSuspensionState()){
				query.active();
			}
		}
		
		if(AmsUtils.isNotNull(queryBean.getAssignee())){
			query.taskAssignee(queryBean.getAssignee());
		}
		
		if(AmsUtils.isNotNull(queryBean.getCandidateUser())){
			query.taskCandidateUser(queryBean.getCandidateUser());
		}
		
		if(AmsUtils.isNotNull(queryBean.getCandidateGroup())){
			query.taskCandidateGroup(queryBean.getCandidateGroup());
		}
		
		query.orderByProcessInstanceId().asc().orderByTaskOwner().asc();
		
		return WrokflowServiceUtils.pageQuery(query);
	}
	
	
	/**
	 * 查询代办任务
	 * 
	 * @param queryBean
	 * @return
	 */
	public List<Task> queryNativeRuTask(RunTaskQueryVO queryBean) {
		StringBuffer sqlsb = new StringBuffer();
		sqlsb.append(" select RES.* ");
		sqlsb.append("   from " + managementService.getTableName(Task.class) + " RES WHERE 1 = 1 ");
		if(AmsUtils.isNotNull(queryBean.getAssignee())){
			sqlsb.append(" AND RES.ASSIGNEE_ = '" + queryBean.getAssignee() + "' ");
		}
		if (AmsUtils.isNotNull(queryBean.getSuspensionState())) {
			sqlsb.append(" AND RES.SUSPENSION_STATE_ = " + queryBean.getSuspensionState()) ;
		}
		if (AmsUtils.isNotNull(queryBean.getNameLike())) {
			sqlsb.append(" RES.NAME_ like %" + queryBean.getSuspensionState() + "%") ;
		}
		
		if (AmsUtils.isNotNull(queryBean.getCandidateUser()) || AmsUtils.isNotNull(queryBean.getCandidateGroup())) {
			sqlsb.append(" UNION ");
			sqlsb.append(" select distinct RES.* ");
			sqlsb.append("   from " + managementService.getTableName(Task.class) + " RES ");
			sqlsb.append("  inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
			sqlsb.append("  WHERE RES.ASSIGNEE_ is null ");
			sqlsb.append("    and I.TYPE_ = 'candidate' ");
			sqlsb.append("    and (I.USER_ID_ = '" + queryBean.getCandidateUser() + "' or I.GROUP_ID_ IN ( " + queryBean.getCandidateGroup() + " )) ");
			if (AmsUtils.isNotNull(queryBean.getSuspensionState())) {
				sqlsb.append(" AND RES.SUSPENSION_STATE_ = " + queryBean.getSuspensionState()) ;
			}
			if (AmsUtils.isNotNull(queryBean.getNameLike())) {
				sqlsb.append(" RES.NAME_ like %" + queryBean.getSuspensionState() + "%") ;
			}
		}
		

		NativeTaskQuery query = taskService.createNativeTaskQuery()
				.sql(" select * FROM ( " + sqlsb.toString() + " ) A order by A.PROC_INST_ID_ asc, A.OWNER_ asc");

		long count = taskService.createNativeTaskQuery().sql("SELECT count(*) FROM ( " + sqlsb.toString() + ")")
				.count();

		return WrokflowServiceUtils.pageQuery(count,query);
	}

	/**
	 * 方法功能描述：查询已办任务
	 * 
	 * @param queryBean
	 * @return
	 */
	public List<HistoricTaskInstance> queryHaveDone(HistoricTaskInstance queryBean) {
		HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery().orderByProcessInstanceId()
				.asc();
		return WrokflowServiceUtils.pageQuery(query);
	}

	/**
	 * 启动流程（有参数）
	 * @param processDefinitionKey 流程定义KEY
	 * @param businessKey 业务主键
	 * @param variables 流程变量
	 * @return
	 */
	public String startProcessInstanceByKey(String processDefinitionKey, String businessKey,
			Map<String, Object> variables) {
		AmsAssert.notNull(businessKey, "业务主键不能为空");
		ProcessInstance pi = rumtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
		return pi.getId();
	}

	/**
	 * 
	 * 方法功能描述：处理任务
	 *
	 * @param taskId
	 * @param tasknodeId
	 * @param param
	 * @return
	 */
	public void completeTask(String procInstId, String taskId, String tasknodeId, HashMap<String, Object> param) {
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		//如果分配人为空，则默认为组任务， 组任务先认领再处理
		if(AmsUtils.isNull(task.getAssignee())){
			taskService.claim(taskId, DataBus.getLoginName());
		}
		completeTask(tasknodeId, param);
	}

	/**
	 * 完成任务（不需要获取流程数据）
	 * 
	 * @param taskId
	 * @param param
	 */
	public void completeTask(String taskId, HashMap<String, Object> param) {
		taskService.setVariablesLocal(taskId, param);
		taskService.complete(taskId, param);
	}

	/**
	 * 方法功能描述：获取高亮流程图
	 * 
	 * @param tasknodeid
	 * @return
	 */
	public String displayProcessDiagram(String tasknodeid) {
		String displayData = null;
		try {
			displayData = processDiagramService.processDiagramHighLightSingle(tasknodeid);
		} catch (Exception e) {
			ExceptionUtil.throwAppException(e);
		}
		return displayData;
	}
	
	/**
	 * 挂起流程实例
	 * @param procInstId
	 */
	public void suspendWork(String procInstId) {
		rumtimeService.suspendProcessInstanceById(procInstId);
	}
	
	/**
	 * 唤醒恢复流程实例
	 * @param procInstId
	 */
	public void activateWork(String procInstId) {
		rumtimeService.activateProcessInstanceById(procInstId);
	}
	
	/**
	 * 删除处理中流程实例
	 * @param procInstId
	 * @param reason 删除原因
	 */
	public void deleteTodoWork(String procInstId,String reason) {
		rumtimeService.deleteProcessInstance(procInstId,reason);
	}
	
	
	/**
	 * 删除已完成流程实例
	 * @param procInstId
	 * @param reason 删除原因
	 */
	public void deleteDownWork(String procInstId,String reason) {
		historyService.deleteHistoricProcessInstance(procInstId);
	}
	
	/**
	 * 查询流程实例
	 * @param processInstanceId
	 * @return
	 */
	public List<ProcessInstance> queryProcessInstance(String processInstanceId){
		return rumtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).list();
	}
	
	/**
	 * 查询历史流程实例
	 * @param processInstanceId
	 * @return
	 */
	public List<HistoricProcessInstance> queryHistoricProcessInstance(String processInstanceId){
		return historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).list();
	}
	
	
	/**
	 * 获取流程变量
	 */
	public List<ApprovalCommentsVO> getProcessVariables(String processInstanceId){
		List<HistoricProcessInstance> hiInstances = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).list();
		if(hiInstances.size() != 1){
			ExceptionUtil.throwAppException("流程实例不存在");
		}
		HistoricProcessInstance historicProcessInstance = hiInstances.get(0);
		List<HistoricTaskInstance> taskhiList =  historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByTaskId().asc().list();
		taskhiList.sort(new Comparator<TaskInfo>() {
			@Override
			public int compare(TaskInfo ti1, TaskInfo ti2) {
				return ti1.getId().compareTo(ti2.getId());
			}
		});
		List<ApprovalCommentsVO> list = new ArrayList<ApprovalCommentsVO>();
		for (HistoricTaskInstance taskInfo : taskhiList) {
			
			//流程实例变量
//			List<HistoricVariableInstance> processVariables = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();
			//任务本地变量
			List<HistoricVariableInstance> taskLocalVariables = historyService.createHistoricVariableInstanceQuery().taskId(taskInfo.getId()).list();
			
			Map<String, Object> variables = new HashMap<String, Object>();
			taskLocalVariables.forEach(hiVariable -> {
		        if (hiVariable.getId() != null && hiVariable.getTaskId() != null) {
		          variables.put(hiVariable.getVariableName(), hiVariable.getValue());
		        }
			});
			ApprovalCommentsVO acvo = new ApprovalCommentsVO();
			acvo.setBusinessKey(historicProcessInstance.getBusinessKey());
			acvo.setProcInstId(processInstanceId);
			acvo.setTaskId(taskInfo.getId());
			acvo.setBusinessKey(historicProcessInstance.getBusinessKey());
			acvo.setHandlerNode(taskInfo.getName());
			acvo.setHandlerRole(taskInfo.getName());
			acvo.setHandlerName(taskInfo.getAssignee());
			acvo.setResult(String.valueOf(variables.getOrDefault(WorkFlowVariable.APPROVAL_RESULT, ApprovalResult.nothing.value)));
			acvo.setComments(String.valueOf(variables.getOrDefault("comments", "无意见")));
			if(null != taskInfo.getStartTime()){
				acvo.setStartTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(taskInfo.getStartTime()));
			}
			if(null != taskInfo.getEndTime()){
				acvo.setEndTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(taskInfo.getEndTime()));
			}
			list.add(acvo);
		}
		return list;
	}
	

}
